"""
__author__ = 'loong'
"""

import os
from xml.dom import minidom
from xml.etree import cElementTree as ET
from functools import wraps

printed = {}


def attr_sorted(attrs):
    sortkeys = [
        "名称",

        "类型",
        "加智力",
        "加武力",
        "加速度",
        "变兵种",
        "描述",

        "归属",
        "年龄",
        "兵种",
        "武力",
        "智力",
        "体力",
        "兵力",
        "经验",
        "等级",
        "忠诚",
        "性格",
        "道具1",
        "道具2",
        "专长",
        "出生地",
        "成年",
        "伯乐",

        "太守",
        "农业",
        "农业上限",
        "商业",
        "商业上限",
        "人口",
        "人口上限",
        "民忠",
        "金钱",
        "粮食",
        "防灾",
        "后备兵力",

        "起始年",

        "备注",
        "doc",
        "id",

        "存档名称",

        "出现年",
        "出现地",
        "寻宝人",
        "name",
        "type",
        "idx",
        "picmax",
        "startfrm",
        "endfrm",
        "x",
        "y",
        "picIdx",
        "cdelay",
        "ndelay",

        "width",
        "height",
        "count",
        "mask",

        "version",
        "宽",
        "高",
        "战斗地图",
        "路径",
    ]
    sortkeys = {k: i for i, k in enumerate(sortkeys)}
    for name in attrs:
        if name not in sortkeys and name not in printed:
            print('need sort key: "{}", '.format(name))
            printed[name] = 1

    def key(a):
        return sortkeys.get(a, 9999)

    return sorted(attrs, key=key)

minidom.sorted = attr_sorted


def pretty_print_xml(xml):
    text = ET.tostring(xml, encoding='UTF-8')
    text = text.replace(b'\x0c', b' ')
    text = text.replace(b'\x08', b' ')
    return minidom.parseString(text).toprettyxml(encoding='UTF-8')


class XmlDataPopulator:
    def __init__(self, define):
        self.define = define

    def populate(self, obj, xml):
        pass


def chunk(src, length):
    return [src[i:i+length] for i in range(0, len(src), length)]


def byte_to_bits(byte):
    bits = []
    for i in range(8):
        v = byte & (0x80 >> i) and 1 or 0
        bits.append(v)
    return bits


def bits_to_byte(bits):
    assert(0 < len(bits) <= 8)
    byte = 0
    for i in range(8):
        if bits[i]:
            byte |= (0x80 >> i)
    return byte


def guard_parents_path(path):
    p = os.path.dirname(path)
    if not os.path.exists(p):
        os.makedirs(p)


has_warning = False


def info(msg):
    global has_warning
    has_warning = True
    print(msg)


def warn(msg):
    info('警告: {}'.format(msg))


def indent(s, n):
    p = ' ' * n
    return os.linesep.join([p + l for l in s.splitlines()])


def dec_raise_xml(f):
    @wraps(f)
    def inner(self, xml, *a, **ka):
        try:
            return f(self, xml, *a, **ka)
        except Exception as e:
            tag = xml.tag
            name = xml.attrib.get('名称') or ""
            if name:
                info = '名称="{}"'.format(name)
            elif tag == '时期':
                info = '起始年="{}"'.format(xml.get('起始年'))
            else:
                info = ''

            raise ValueError('<{} {}>{}{}'.format(xml.tag, info, os.linesep, indent(str(e), 4)))
    return inner

